// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.core.skinnedmodel.model;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Quaternion;
import org.lwjgl.util.vector.Vector3f;
import zombie.core.opengl.RenderThread;
import zombie.core.skinnedmodel.ModelManager;
import zombie.core.skinnedmodel.animation.AnimationClip;
import zombie.core.skinnedmodel.animation.Keyframe;
import zombie.core.skinnedmodel.animation.StaticAnimation;
import zombie.util.SharedStrings;

public final class ModelLoader {
    public static final ModelLoader instance = new ModelLoader();
    private final ThreadLocal<SharedStrings> sharedStrings = ThreadLocal.withInitial(SharedStrings::new);

    protected ModelTxt loadTxt(String string0, boolean boolean0, boolean boolean1, SkinningData skinningData) throws IOException {
        ModelTxt modelTxt = new ModelTxt();
        modelTxt.bStatic = boolean0;
        modelTxt.bReverse = boolean1;
        VertexBufferObject.VertexFormat vertexFormat = new VertexBufferObject.VertexFormat(boolean0 ? 4 : 6);
        vertexFormat.setElement(0, VertexBufferObject.VertexType.VertexArray, 12);
        vertexFormat.setElement(1, VertexBufferObject.VertexType.NormalArray, 12);
        vertexFormat.setElement(2, VertexBufferObject.VertexType.TangentArray, 12);
        vertexFormat.setElement(3, VertexBufferObject.VertexType.TextureCoordArray, 8);
        if (!boolean0) {
            vertexFormat.setElement(4, VertexBufferObject.VertexType.BlendWeightArray, 16);
            vertexFormat.setElement(5, VertexBufferObject.VertexType.BlendIndexArray, 16);
        }

        vertexFormat.calculate();
        FileReader fileReader = new FileReader(string0);

        try {
            BufferedReader bufferedReader = new BufferedReader(fileReader);

            try {
                SharedStrings sharedStringsx = (SharedStrings)this.sharedStrings.get();
                ModelLoader.LoadMode loadMode = ModelLoader.LoadMode.Version;
                String string1 = null;
                int int0 = 0;
                int int1 = 0;
                int int2 = 0;
                int int3 = 0;
                int int4 = 0;
                boolean boolean2 = false;

                while ((string1 = bufferedReader.readLine()) != null) {
                    if (string1.indexOf(35) != 0) {
                        if (string1.contains("Tangent")) {
                            if (boolean0) {
                                int0 += 2;
                            }

                            boolean2 = true;
                        }

                        if (int0 > 0) {
                            int0--;
                        } else {
                            switch (loadMode) {
                                case Version:
                                    loadMode = ModelLoader.LoadMode.ModelName;
                                    break;
                                case ModelName:
                                    loadMode = ModelLoader.LoadMode.VertexStrideElementCount;
                                    break;
                                case VertexStrideElementCount:
                                    loadMode = ModelLoader.LoadMode.VertexCount;
                                    if (boolean0) {
                                        int0 = 7;
                                    } else {
                                        int0 = 13;
                                    }
                                    break;
                                case VertexCount:
                                    int1 = Integer.parseInt(string1);
                                    loadMode = ModelLoader.LoadMode.VertexBuffer;
                                    modelTxt.vertices = new VertexBufferObject.VertexArray(vertexFormat, int1);
                                    break;
                                case VertexBuffer:
                                    int int5 = 0;

                                    for (; int5 < int1; int5++) {
                                        String[] string2 = string1.split(",");
                                        float float0 = Float.parseFloat(string2[0].trim());
                                        float float1 = Float.parseFloat(string2[1].trim());
                                        float float2 = Float.parseFloat(string2[2].trim());
                                        string1 = bufferedReader.readLine();
                                        string2 = string1.split(",");
                                        float float3 = Float.parseFloat(string2[0].trim());
                                        float float4 = Float.parseFloat(string2[1].trim());
                                        float float5 = Float.parseFloat(string2[2].trim());
                                        float float6 = 0.0F;
                                        float float7 = 0.0F;
                                        float float8 = 0.0F;
                                        if (boolean2) {
                                            string1 = bufferedReader.readLine();
                                            string2 = string1.split(",");
                                            float6 = Float.parseFloat(string2[0].trim());
                                            float7 = Float.parseFloat(string2[1].trim());
                                            float8 = Float.parseFloat(string2[2].trim());
                                        }

                                        string1 = bufferedReader.readLine();
                                        string2 = string1.split(",");
                                        float float9 = Float.parseFloat(string2[0].trim());
                                        float float10 = Float.parseFloat(string2[1].trim());
                                        float float11 = 0.0F;
                                        float float12 = 0.0F;
                                        float float13 = 0.0F;
                                        float float14 = 0.0F;
                                        int int6 = 0;
                                        int int7 = 0;
                                        int int8 = 0;
                                        int int9 = 0;
                                        if (!boolean0) {
                                            string1 = bufferedReader.readLine();
                                            string2 = string1.split(",");
                                            float11 = Float.parseFloat(string2[0].trim());
                                            float12 = Float.parseFloat(string2[1].trim());
                                            float13 = Float.parseFloat(string2[2].trim());
                                            float14 = Float.parseFloat(string2[3].trim());
                                            string1 = bufferedReader.readLine();
                                            string2 = string1.split(",");
                                            int6 = Integer.parseInt(string2[0].trim());
                                            int7 = Integer.parseInt(string2[1].trim());
                                            int8 = Integer.parseInt(string2[2].trim());
                                            int9 = Integer.parseInt(string2[3].trim());
                                        }

                                        string1 = bufferedReader.readLine();
                                        modelTxt.vertices.setElement(int5, 0, float0, float1, float2);
                                        modelTxt.vertices.setElement(int5, 1, float3, float4, float5);
                                        modelTxt.vertices.setElement(int5, 2, float6, float7, float8);
                                        modelTxt.vertices.setElement(int5, 3, float9, float10);
                                        if (!boolean0) {
                                            modelTxt.vertices.setElement(int5, 4, float11, float12, float13, float14);
                                            modelTxt.vertices.setElement(int5, 5, (float)int6, (float)int7, (float)int8, (float)int9);
                                        }
                                    }

                                    loadMode = ModelLoader.LoadMode.NumberOfFaces;
                                    break;
                                case NumberOfFaces:
                                    int2 = Integer.parseInt(string1);
                                    modelTxt.elements = new int[int2 * 3];
                                    loadMode = ModelLoader.LoadMode.FaceData;
                                    break;
                                case FaceData:
                                    for (int int19 = 0; int19 < int2; int19++) {
                                        String[] string17 = string1.split(",");
                                        int int20 = Integer.parseInt(string17[0].trim());
                                        int int21 = Integer.parseInt(string17[1].trim());
                                        int int22 = Integer.parseInt(string17[2].trim());
                                        if (boolean1) {
                                            modelTxt.elements[int19 * 3 + 2] = int20;
                                            modelTxt.elements[int19 * 3 + 1] = int21;
                                            modelTxt.elements[int19 * 3 + 0] = int22;
                                        } else {
                                            modelTxt.elements[int19 * 3 + 0] = int20;
                                            modelTxt.elements[int19 * 3 + 1] = int21;
                                            modelTxt.elements[int19 * 3 + 2] = int22;
                                        }

                                        string1 = bufferedReader.readLine();
                                    }

                                    loadMode = ModelLoader.LoadMode.NumberOfBones;
                                    break;
                                case NumberOfBones:
                                    int4 = Integer.parseInt(string1);
                                    loadMode = ModelLoader.LoadMode.SkeletonHierarchy;
                                    break;
                                case SkeletonHierarchy:
                                    for (int int16 = 0; int16 < int4; int16++) {
                                        int int17 = Integer.parseInt(string1);
                                        string1 = bufferedReader.readLine();
                                        int int18 = Integer.parseInt(string1);
                                        string1 = bufferedReader.readLine();
                                        String string16 = sharedStringsx.get(string1);
                                        string1 = bufferedReader.readLine();
                                        modelTxt.SkeletonHierarchy.add(int18);
                                        modelTxt.boneIndices.put(string16, int17);
                                    }

                                    loadMode = ModelLoader.LoadMode.BindPose;
                                    break;
                                case BindPose:
                                    for (int int15 = 0; int15 < int4; int15++) {
                                        string1 = bufferedReader.readLine();
                                        String string13 = bufferedReader.readLine();
                                        String string14 = bufferedReader.readLine();
                                        String string15 = bufferedReader.readLine();
                                        modelTxt.bindPose.add(int15, this.getMatrix(string1, string13, string14, string15));
                                        string1 = bufferedReader.readLine();
                                    }

                                    loadMode = ModelLoader.LoadMode.InvBindPose;
                                    break;
                                case InvBindPose:
                                    for (int int14 = 0; int14 < int4; int14++) {
                                        string1 = bufferedReader.readLine();
                                        String string10 = bufferedReader.readLine();
                                        String string11 = bufferedReader.readLine();
                                        String string12 = bufferedReader.readLine();
                                        modelTxt.invBindPose.add(int14, this.getMatrix(string1, string10, string11, string12));
                                        string1 = bufferedReader.readLine();
                                    }

                                    loadMode = ModelLoader.LoadMode.SkinOffsetMatrices;
                                    break;
                                case SkinOffsetMatrices:
                                    for (int int13 = 0; int13 < int4; int13++) {
                                        string1 = bufferedReader.readLine();
                                        String string7 = bufferedReader.readLine();
                                        String string8 = bufferedReader.readLine();
                                        String string9 = bufferedReader.readLine();
                                        modelTxt.skinOffsetMatrices.add(int13, this.getMatrix(string1, string7, string8, string9));
                                        string1 = bufferedReader.readLine();
                                    }

                                    loadMode = ModelLoader.LoadMode.NumberOfAnims;
                                    break;
                                case NumberOfAnims:
                                    int3 = Integer.parseInt(string1);
                                    loadMode = ModelLoader.LoadMode.Anim;
                                    break;
                                case Anim:
                                    ArrayList arrayList0 = new ArrayList();
                                    string1 = bufferedReader.readLine();
                                    float float15 = Float.parseFloat(string1);
                                    string1 = bufferedReader.readLine();
                                    int int10 = Integer.parseInt(string1);
                                    string1 = bufferedReader.readLine();

                                    for (int int11 = 0; int11 < int10; int11++) {
                                        Keyframe keyframe0 = new Keyframe();
                                        int int12 = Integer.parseInt(string1);
                                        String string3 = bufferedReader.readLine();
                                        String string4 = sharedStringsx.get(string3);
                                        String string5 = bufferedReader.readLine();
                                        float float16 = Float.parseFloat(string5);
                                        string1 = bufferedReader.readLine();
                                        String string6 = bufferedReader.readLine();
                                        Vector3f vector3f = this.getVector(string1);
                                        Quaternion quaternion = this.getQuaternion(string6);
                                        if (int11 < int10 - 1) {
                                            string1 = bufferedReader.readLine();
                                        }

                                        keyframe0.Bone = int12;
                                        keyframe0.BoneName = string4;
                                        keyframe0.Time = float16;
                                        keyframe0.Rotation = quaternion;
                                        keyframe0.Position = new Vector3f(vector3f);
                                        arrayList0.add(keyframe0);
                                    }

                                    AnimationClip animationClip0 = new AnimationClip(float15, arrayList0, string1, false);
                                    arrayList0.clear();
                                    if (ModelManager.instance.bCreateSoftwareMeshes) {
                                        animationClip0.staticClip = new StaticAnimation(animationClip0);
                                    }

                                    modelTxt.clips.put(string1, animationClip0);
                            }
                        }
                    }
                }

                if (!boolean0 && skinningData != null) {
                    try {
                        int[] int23 = new int[modelTxt.boneIndices.size()];
                        ArrayList arrayList1 = modelTxt.SkeletonHierarchy;
                        HashMap hashMap0 = modelTxt.boneIndices;
                        HashMap hashMap1 = new HashMap(skinningData.BoneIndices);
                        ArrayList arrayList2 = new ArrayList(skinningData.SkeletonHierarchy);
                        hashMap0.forEach((string, integer) -> {
                            int int0x = (Integer)hashMap1.getOrDefault(string, -1);
                            if (int0x == -1) {
                                int0x = hashMap1.size();
                                hashMap1.put(string, int0x);
                                int int1x = (Integer)arrayList1.get(integer);
                                if (int1x >= 0) {
                                    arrayList2.add(int23[int1x]);
                                } else {
                                    byte _byte = -2;
                                }
                            }

                            int23[integer] = int0x;
                        });
                        modelTxt.boneIndices = hashMap1;
                        modelTxt.SkeletonHierarchy = arrayList2;

                        for (int int24 = 0; int24 < modelTxt.vertices.m_numVertices; int24++) {
                            int int25 = (int)modelTxt.vertices.getElementFloat(int24, 5, 0);
                            int int26 = (int)modelTxt.vertices.getElementFloat(int24, 5, 1);
                            int int27 = (int)modelTxt.vertices.getElementFloat(int24, 5, 2);
                            int int28 = (int)modelTxt.vertices.getElementFloat(int24, 5, 3);
                            if (int25 >= 0) {
                                int25 = int23[int25];
                            }

                            if (int26 >= 0) {
                                int26 = int23[int26];
                            }

                            if (int27 >= 0) {
                                int27 = int23[int27];
                            }

                            if (int28 >= 0) {
                                int28 = int23[int28];
                            }

                            modelTxt.vertices.setElement(int24, 5, (float)int25, (float)int26, (float)int27, (float)int28);
                        }

                        for (AnimationClip animationClip1 : modelTxt.clips.values()) {
                            for (Keyframe keyframe1 : animationClip1.getKeyframes()) {
                                keyframe1.Bone = int23[keyframe1.Bone];
                            }
                        }

                        modelTxt.skinOffsetMatrices = this.RemapMatrices(int23, modelTxt.skinOffsetMatrices, modelTxt.boneIndices.size());
                        modelTxt.bindPose = this.RemapMatrices(int23, modelTxt.bindPose, modelTxt.boneIndices.size());
                        modelTxt.invBindPose = this.RemapMatrices(int23, modelTxt.invBindPose, modelTxt.boneIndices.size());
                    } catch (Exception exception) {
                        exception.toString();
                    }
                }
            } catch (Throwable throwable0) {
                try {
                    bufferedReader.close();
                } catch (Throwable throwable1) {
                    throwable0.addSuppressed(throwable1);
                }

                throw throwable0;
            }

            bufferedReader.close();
        } catch (Throwable throwable2) {
            try {
                fileReader.close();
            } catch (Throwable throwable3) {
                throwable2.addSuppressed(throwable3);
            }

            throw throwable2;
        }

        fileReader.close();
        return modelTxt;
    }

    protected void applyToMesh(ModelTxt modelTxt, ModelMesh modelMesh, SkinningData skinningData) {
        if (modelTxt.bStatic) {
            if (!ModelManager.NoOpenGL) {
                modelMesh.m_bHasVBO = true;
                RenderThread.queueInvokeOnRenderContext(() -> {
                    modelMesh.SetVertexBuffer(new VertexBufferObject(modelTxt.vertices, modelTxt.elements));
                    if (ModelManager.instance.bCreateSoftwareMeshes) {
                        modelMesh.softwareMesh.vb = modelMesh.vb;
                    }
                });
            }
        } else {
            modelMesh.skinningData = new SkinningData(
                modelTxt.clips, modelTxt.bindPose, modelTxt.invBindPose, modelTxt.skinOffsetMatrices, modelTxt.SkeletonHierarchy, modelTxt.boneIndices
            );
            if (!ModelManager.NoOpenGL) {
                modelMesh.m_bHasVBO = true;
                RenderThread.queueInvokeOnRenderContext(() -> {
                    modelMesh.SetVertexBuffer(new VertexBufferObject(modelTxt.vertices, modelTxt.elements, modelTxt.bReverse));
                    if (ModelManager.instance.bCreateSoftwareMeshes) {
                    }
                });
            }
        }

        if (skinningData != null) {
            modelMesh.skinningData.AnimationClips = skinningData.AnimationClips;
        }
    }

    protected void applyToAnimation(ModelTxt modelTxt, AnimationAsset animationAsset) {
        animationAsset.AnimationClips = modelTxt.clips;
        animationAsset.assetParams.animationsMesh.skinningData.AnimationClips.putAll(modelTxt.clips);
    }

    private ArrayList<Matrix4f> RemapMatrices(int[] int3, ArrayList<Matrix4f> arrayList1, int int0) {
        ArrayList arrayList0 = new ArrayList(int0);
        Matrix4f matrix4f = new Matrix4f();

        for (int int1 = 0; int1 < int0; int1++) {
            arrayList0.add(matrix4f);
        }

        for (int int2 = 0; int2 < int3.length; int2++) {
            arrayList0.set(int3[int2], (Matrix4f)arrayList1.get(int2));
        }

        return arrayList0;
    }

    private Vector3f getVector(String string1) {
        Vector3f vector3f = new Vector3f();
        String[] string0 = string1.split(",");
        vector3f.x = Float.parseFloat(string0[0]);
        vector3f.y = Float.parseFloat(string0[1]);
        vector3f.z = Float.parseFloat(string0[2]);
        return vector3f;
    }

    private Quaternion getQuaternion(String string1) {
        Quaternion quaternion = new Quaternion();
        String[] string0 = string1.split(",");
        quaternion.x = Float.parseFloat(string0[0]);
        quaternion.y = Float.parseFloat(string0[1]);
        quaternion.z = Float.parseFloat(string0[2]);
        quaternion.w = Float.parseFloat(string0[3]);
        return quaternion;
    }

    private Matrix4f getMatrix(String string1, String string2, String string3, String string4) {
        Matrix4f matrix4f = new Matrix4f();
        boolean _boolean = false;
        String[] string0 = string1.split(",");
        matrix4f.m00 = Float.parseFloat(string0[0]);
        matrix4f.m01 = Float.parseFloat(string0[1]);
        matrix4f.m02 = Float.parseFloat(string0[2]);
        matrix4f.m03 = Float.parseFloat(string0[3]);
        string0 = string2.split(",");
        matrix4f.m10 = Float.parseFloat(string0[0]);
        matrix4f.m11 = Float.parseFloat(string0[1]);
        matrix4f.m12 = Float.parseFloat(string0[2]);
        matrix4f.m13 = Float.parseFloat(string0[3]);
        string0 = string3.split(",");
        matrix4f.m20 = Float.parseFloat(string0[0]);
        matrix4f.m21 = Float.parseFloat(string0[1]);
        matrix4f.m22 = Float.parseFloat(string0[2]);
        matrix4f.m23 = Float.parseFloat(string0[3]);
        string0 = string4.split(",");
        matrix4f.m30 = Float.parseFloat(string0[0]);
        matrix4f.m31 = Float.parseFloat(string0[1]);
        matrix4f.m32 = Float.parseFloat(string0[2]);
        matrix4f.m33 = Float.parseFloat(string0[3]);
        return matrix4f;
    }

    public static enum LoadMode {
        Version,
        ModelName,
        VertexStrideElementCount,
        VertexStrideSize,
        VertexStrideData,
        VertexCount,
        VertexBuffer,
        NumberOfFaces,
        FaceData,
        NumberOfBones,
        SkeletonHierarchy,
        BindPose,
        InvBindPose,
        SkinOffsetMatrices,
        NumberOfAnims,
        Anim;
    }
}
